_compat.py 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. import sys
  2. import platform
  3. __all__ = ['install', 'NullFinder', 'Protocol']
  4. try:
  5. from typing import Protocol
  6. except ImportError: # pragma: no cover
  7. from typing_extensions import Protocol # type: ignore
  8. def install(cls):
  9. """
  10. Class decorator for installation on sys.meta_path.
  11. Adds the backport DistributionFinder to sys.meta_path and
  12. attempts to disable the finder functionality of the stdlib
  13. DistributionFinder.
  14. """
  15. sys.meta_path.append(cls())
  16. disable_stdlib_finder()
  17. return cls
  18. def disable_stdlib_finder():
  19. """
  20. Give the backport primacy for discovering path-based distributions
  21. by monkey-patching the stdlib O_O.
  22. See #91 for more background for rationale on this sketchy
  23. behavior.
  24. """
  25. def matches(finder):
  26. return getattr(
  27. finder, '__module__', None
  28. ) == '_frozen_importlib_external' and hasattr(finder, 'find_distributions')
  29. for finder in filter(matches, sys.meta_path): # pragma: nocover
  30. del finder.find_distributions
  31. class NullFinder:
  32. """
  33. A "Finder" (aka "MetaClassFinder") that never finds any modules,
  34. but may find distributions.
  35. """
  36. @staticmethod
  37. def find_spec(*args, **kwargs):
  38. return None
  39. # In Python 2, the import system requires finders
  40. # to have a find_module() method, but this usage
  41. # is deprecated in Python 3 in favor of find_spec().
  42. # For the purposes of this finder (i.e. being present
  43. # on sys.meta_path but having no other import
  44. # system functionality), the two methods are identical.
  45. find_module = find_spec
  46. def pypy_partial(val):
  47. """
  48. Adjust for variable stacklevel on partial under PyPy.
  49. Workaround for #327.
  50. """
  51. is_pypy = platform.python_implementation() == 'PyPy'
  52. return val + is_pypy